package sub

import (
	"fmt"
	"quipus/cmd/qpc/sub"
	"quipus/internal/utils"
	v1pb "quipus/proto/gen/api/v1"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
)

var (
	flows      []string
	flowId     int32
	granaryIds []int32
)

func init() {
	createCmd.PersistentFlags().StringSliceVarP(&flows, "workflow", "w", []string{}, "the workflow list,format: {name}|{assiter id}|{type}|{input_len}|{head or tail or none}|{scope:subject,workflow}|{granary1&granary2}|{description}}|{next_name1&nextname2}")
	flowCmd.AddCommand(createCmd)
}

var createCmd = &cobra.Command{
	Use:   "create",
	Short: "Run the cmd to create subject",
	RunE: func(cmd *cobra.Command, args []string) error {
		qconn, e := sub.NewGrpcConnect(sub.QpConfig.QPAddress)
		if e != nil {
			return e
		}

		qclient := v1pb.NewWorkflowServiceClient(qconn)
		ctxWithToken := sub.NewCtxWithToken(sub.QpConfig.Token)

		if len(flows) < 1 {
			return fmt.Errorf("workflow is empty")
		}

		flowMap := make(map[string]*v1pb.Workflow)
		var workflow *v1pb.Workflow

		for _, f := range flows {
			flowArray := strings.Split(f, "|")
			if len(flowArray) < 7 {
				return fmt.Errorf("workflow format error")
			}
			//name
			wf := flowMap[flowArray[0]]
			if wf == nil {
				wf = &v1pb.Workflow{Name: flowArray[0]}
			}

			// assistant
			if flowArray[1] != "" {
				a, e := strconv.Atoi(flowArray[1])
				if e != nil {
					return e
				}
				wf.Assistant = utils.BuildUrn(utils.AssistantUrnPrefix, int32(a))
			}

			if flowArray[2] != "" {
				flowType := strings.ToUpper(flowArray[2])
				switch flowType {
				case "GATHER":
					wf.WorkType = v1pb.WorkType_GATHER_WORK
					break
				case "REDUCE":
					wf.WorkType = v1pb.WorkType_REDUCE_WORK
					break
				default:
					wf.WorkType = v1pb.WorkType_WORK_TYPE_UNKOWN
				}
			}

			if flowArray[3] != "" {
				// input len
				i, e := strconv.Atoi(flowArray[3])
				if e != nil {
					return e
				}
				wf.InputLen = int32(i)
			}

			if flowArray[4] != "" {
				// workflow node pos
				pos := strings.ToUpper(flowArray[4])
				switch pos {
				case "HEAD":
					wf.Pos = v1pb.FlowPos_FLOW_HEAD
					break
				case "TAIL":
					wf.Pos = v1pb.FlowPos_FLOW_TAIL
					break
				default:
					wf.Pos = v1pb.FlowPos_FLOW_POS_UNKOWN
				}
			}

			if flowArray[5] != "" {
				// granary scope
				scope := strings.ToUpper(flowArray[5])
				switch scope {
				case "SUBJECT":
					wf.GranaryScope = v1pb.GranaryScope_SUBJECT_GRANARY
					break
				case "WORKFLOW":
					wf.GranaryScope = v1pb.GranaryScope_WORKFLOW_GRANARY
					break
				default:
					wf.GranaryScope = v1pb.GranaryScope_UNUSE_GRANARY
				}
			}

			if flowArray[6] != "" {
				// granary
				granaries := flowArray[6]
				if granaries != "" {
					gArray := strings.Split(granaries, "&")
					for _, g := range gArray {
						i, e := strconv.Atoi(g)
						if e != nil {
							return e
						}
						gs := utils.BuildUrn(utils.GranaryUrnPrefix, int32(i))
						wf.Granaries = append(wf.Granaries, gs)
					}
				}
			}

			wf.Description = flowArray[7]
			if len(flowArray) > 8 {
				chs := strings.Split(flowArray[8], "&")
				for _, c := range chs {
					next := flowMap[c]
					if next == nil {
						next = &v1pb.Workflow{Name: c}
						flowMap[c] = next
					}
					wf.Next = append(wf.Next, next)
				}
			}

			if wf.Pos == v1pb.FlowPos_FLOW_HEAD {
				workflow = wf
			} else {
				flowMap[wf.Name] = wf
			}

		}

		in := &v1pb.CreateWorkflowRequest{Workflow: workflow}

		rsp, err := qclient.CreateWorkflow(ctxWithToken, in)
		if err != nil {
			return err
		}
		fmt.Print(rsp)
		return nil
	},
}
